/**
 * 猫狗分类器模型测试脚本
 * 功能：测试训练好的模型效果，评估识别准确率和平衡度
 * 使用方法：npm test
 */

// 引入自定义的简单图像分类器类
const SimpleImageClassifier = require('../models/simple_classifier');
// 引入Node.js路径处理模块，用于构建文件路径
const path = require('path');
// 引入Node.js文件系统模块，用于检查文件存在性和读取目录
const fs = require('fs');

/**
 * 异步测试指定模型的函数
 * @param {string} modelPath - 模型文件的路径
 * @param {string} modelName - 模型的显示名称
 * @returns {Object|null} 测试结果对象或null（测试失败时）
 */
async function testModel(modelPath, modelName) {
  // 打印测试开始信息和分隔线
  console.log(`\n🧪 测试模型: ${modelName}`);
  console.log('-'.repeat(40)); // 输出40个短横线作为分隔线
  
  try {
    // 创建分类器实例用于加载和测试模型
    const classifier = new SimpleImageClassifier();
    
    // 检查模型文件是否存在
    if (!fs.existsSync(modelPath)) {
      console.log(`❌ 模型文件不存在: ${modelPath}`);
      return null; // 文件不存在时返回null
    }
    
    // 从文件加载训练好的模型权重
    classifier.loadModel(modelPath);
    console.log('✅ 模型加载成功');
    
    // 设置测试图片目录路径
    const testDir = './images/test1';
    // 检查测试目录是否存在
    if (!fs.existsSync(testDir)) {
      console.log('❌ 测试目录不存在');
      return null; // 目录不存在时返回null
    }
    
    // 读取测试目录中的JPG文件，只取前20张进行测试
    const testFiles = fs.readdirSync(testDir)
      .filter(f => f.endsWith('.jpg')) // 过滤出JPG格式的图片文件
      .slice(0, 20); // 只取前20张图片进行快速测试
    
    // 初始化统计变量
    let catCount = 0;        // 识别为猫的图片数量
    let dogCount = 0;        // 识别为狗的图片数量
    let totalConfidence = 0; // 总置信度，用于计算平均值
    
    console.log('📊 开始测试...');
    
    // 遍历每个测试文件进行预测
    for (const file of testFiles) {
      // 对当前图片进行预测
      const result = await classifier.predict(path.join(testDir, file));
      if (result) { // 预测成功时
        // 根据预测结果更新计数器
        if (result.className === 'cat') catCount++;
        else dogCount++;
        // 累加置信度用于后续计算平均值
        totalConfidence += result.confidence;
        
        // 根据预测类别选择对应的emoji表情
        const emoji = result.className === 'cat' ? '🐱' : '🐶';
        // 打印每张图片的预测结果和置信度
        console.log(`${file}: ${emoji} ${result.className} (${(result.confidence * 100).toFixed(1)}%)`);
      }
    }
    
    // 计算测试统计指标
    const avgConfidence = totalConfidence / testFiles.length; // 平均置信度
    const balance = Math.abs(catCount - dogCount) / testFiles.length; // 平衡度（越接近0越好）
    
    // 打印测试结果统计
    console.log(`\n📊 ${modelName} 测试结果:`);
    console.log(`   猫: ${catCount} 张 (${(catCount/testFiles.length*100).toFixed(1)}%)`);
    console.log(`   狗: ${dogCount} 张 (${(dogCount/testFiles.length*100).toFixed(1)}%)`);
    console.log(`   平均置信度: ${(avgConfidence * 100).toFixed(1)}%`);
    console.log(`   平衡度: ${(balance * 100).toFixed(1)}% (越低越好)`);
    
    // 返回测试结果对象，包含所有统计信息
    return {
      name: modelName,           // 模型名称
      path: modelPath,          // 模型文件路径
      catCount,                 // 识别为猫的数量
      dogCount,                 // 识别为狗的数量
      avgConfidence,            // 平均置信度
      balance,                  // 平衡度指标
      total: testFiles.length   // 测试图片总数
    };
    
  } catch (error) {
    // 捕获测试过程中的错误并打印
    console.log(`❌ 测试失败: ${error.message}`);
    return null; // 测试失败时返回null
  }
}

/**
 * 异步测试当前模型的主函数
 * 测试默认的simple_model.json模型并评估其性能
 */
async function testCurrentModel() {
  // 打印测试开始信息
  console.log('🔍 测试当前模型');
  console.log('=' .repeat(50)); // 输出50个等号作为分隔线
  
  // 设置当前模型的文件路径
  const modelPath = './models/simple_model.json';
  // 调用testModel函数测试当前模型
  const result = await testModel(modelPath, '当前模型');
  
  // 检查测试是否成功
  if (!result) {
    console.log('❌ 模型测试失败');
    console.log('💡 请先运行训练: node train.js');
    return; // 测试失败时直接返回
  }
  
  // 打印详细的测试总结
  console.log('\n📊 测试总结:');
  console.log('=' .repeat(30)); // 输出30个等号作为分隔线
  console.log(`✅ 模型文件: ${result.path}`);
  console.log(`📈 识别分布: 猫${result.catCount}张 狗${result.dogCount}张`);
  console.log(`🎯 平均置信度: ${(result.avgConfidence * 100).toFixed(1)}%`);
  console.log(`⚖️  平衡度: ${(result.balance * 100).toFixed(1)}%`);
  
  // 根据测试结果评估模型质量
  if (result.balance < 0.3 && result.avgConfidence > 0.5) {
    // 平衡度好且置信度高：优秀模型
    console.log('🎉 模型质量: 优秀');
  } else if (result.balance < 0.5 && result.avgConfidence > 0.45) {
    // 平衡度较好且置信度中等：良好模型
    console.log('👍 模型质量: 良好');
  } else {
    // 其他情况：需要改进的模型
    console.log('⚠️  模型质量: 需要改进');
    console.log('💡 建议重新训练: node train.js');
  }
  
  // 检查服务器文件状态
  console.log('\n⚙️  服务器状态:');
  const serverPath = './src/server/simple_server.js';
  // 检查服务器文件是否存在
  if (fs.existsSync(serverPath)) {
    console.log('✅ 服务器文件存在');
    console.log('🚀 启动命令: node src/server/simple_server.js');
  } else {
    console.log('❌ 服务器文件不存在');
  }
}

// 立即执行测试函数，开始模型测试流程
testCurrentModel();
